package parser

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

type GithubParser struct {
	repo string
}

// NewGithubParser 创建一个 GithubParser
func NewGithubParser(repo string) *GithubParser {
	return &GithubParser{
		repo: repo,
	}
}

// repoToUrl 内部函数
// 预期将 user/repo 转换为 https://github.com/user/repo
func (gp *GithubParser) repoToUrl() (url string) {
	if strings.HasPrefix(gp.repo, "http") {
		url = gp.repo
	} else {
		url = "https://github.com/" + gp.repo
	}
	return
}

// GetLatestTagLocation
func (gp *GithubParser) GetLatestTagLocation() (location string, err error) {
	url := gp.repoToUrl() + "/releases/latest"

	client := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}

	head, err := client.Head(url)
	if err != nil {
		return
	}
	location = head.Header.Get("Location")

	return
}

// GetReleaseHtml 获取发布页面 HTML 内容
func (gp *GithubParser) GetReleaseTagHtml(url string) (html string, err error) {
	// https://github.com/user/repo/releases/tag/<tag>
	// https://github.com/zinface/user/repo/releases/expanded_assets/<tag>

	if url == "" {
		url, err = gp.GetLatestTagLocation()
		if err != nil {
			return
		}
		url = strings.Replace(url, "/tag/", "/expanded_assets/", 1)
	}

	fmt.Printf("url: %v\n", url)

	resp, err := http.Get(url)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	data, err := io.ReadAll(resp.Body)
	html = string(data)

	return
}

type ReleaseFile struct {
	Url      string
	FileName string
}

// ReleaseHtmlToFiles 解析 github 发布页面，返回文件列表
func (gp *GithubParser) ReleaseHtmlToFiles(html string) (files []ReleaseFile, err error) {
	if html == "" {
		html, err = gp.GetReleaseTagHtml("")
	}
	doc, _ := goquery.NewDocumentFromReader(bytes.NewReader([]byte(html)))
	doc.Find("a").Each(func(i int, s *goquery.Selection) {
		href, _ := s.Attr("href")
		if href != "" {
			files = append(files, ReleaseFile{
				Url:      fmt.Sprintf("http://github.com%v", href),
				FileName: splitLast(href, "/"),
			})
		}
	})
	return
}

func (gp *GithubParser) GetLatestFiles() (files []ReleaseFile, err error) {
	return gp.ReleaseHtmlToFiles("")
}

func splitLast(s string, sep string) string {
	splits := strings.Split(s, sep)
	return splits[len(splits)-1]
}
